
const getStringSizeInBytes = (str) => {
  const encoder = new TextEncoder();
  const encoded = encoder.encode(str);
  return {
    file: encoded,
    size: encoded.length
  };
}

const decodeStringFromBytes = (uint8Array) => {
  const decoder = new TextDecoder('utf-8');
  return decoder.decode(uint8Array);
}

const getStore = (key) => {
  if(!window.utools)return null
  let value = utools.dbStorage.getItem(key)
  if(!value)return null;
  return JSON.parse(value);
}

const getStoreByChunks = (key) => {
  if(!window.utools)return
  let chunks = [], bool = true;
  while(bool){
    bool = utools.db.getAttachment(`${key}_${chunks.length}`)
    if(!!bool)chunks.push(bool)
  }
  if(chunks.length === 0)return null;
  return JSON.parse(mergeFile(chunks));
}

const getIds = (id) => {
  if(!window.utools)return
  let keys = [], bool = true;
  while(bool){
    bool = utools.db.getAttachment(`${id}_${keys.length}`)
    if(!!bool)keys.push(`${id}_${keys.length}`)
  }
  if(keys.length === 0)return null;
  return keys
}

const setStore = (key, data) => {
  if(!window.utools)return
  utools.dbStorage.setItem(key, JSON.stringify(data));
}

const setStoreByChunks = async (key, data) => {
  if(!window.utools)return
  deleteStoreByChunks(key)
  
  let chunks = sliceFile(JSON.stringify(data))
  
  if(Array.isArray(chunks)){
    chunks.forEach((file, index) => {
      utools.db.promises.postAttachment(`${key}_${index}`, file, 'text/plain');
    })
  }else{
    utools.db.promises.postAttachment(`${key}_0`, chunks, 'text/plain');
  }
}

const deleteStoreByChunks = (key) => {
  if(!window.utools)return
  let keys = getIds(key)
  if(keys)keys.forEach(item=>utools.db.remove(item))
}

const sliceFile = (file, size = 1024 * 1024 * 9.5) => {
  let {
    file: f, size: length
  } = getStringSizeInBytes(file)
  
  if(length > size){
    const chunks = [];
    let offset = 0;
  
    while (offset < length) {
      const chunk = f.slice(offset, offset + size);
      chunks.push(chunk);
      offset += size;
    }
    return chunks;
  }

  return f
}

const mergeFile = (chunks) => {
  const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
  const mergedArray = new Uint8Array(totalLength);
  
  let offset = 0;
  for (let chunk of chunks) {
    mergedArray.set(chunk, offset);
    offset += chunk.length;
  }
  
  return decodeStringFromBytes(mergedArray);
}


// const mergeFile = (chunks) => {
//   let file = chunks.reduce((acc, chunk)=>acc + chunk, '')
//   return file;
// }


export { getStore, setStore, sliceFile, mergeFile, decodeStringFromBytes, getStoreByChunks, setStoreByChunks, deleteStoreByChunks }